package com.shrct.businessprocess.purchase.impl;

import com.google.common.base.Objects;
import com.shrct.businessprocess.budget.RCBudget;
import com.shrct.businessprocess.budget.impl.RCBudgetImpl;
import com.shrct.businessprocess.organization.RCEnterprise;
import com.shrct.businessprocess.product.RCProductEntry;
import com.shrct.businessprocess.product.RCProductServiceTracer;
import com.shrct.businessprocess.product.RCProductSpecification;
import com.shrct.businessprocess.project.RCCustomerContract;
import com.shrct.businessprocess.project.RCExchangeRate;
import com.shrct.businessprocess.project.RCProjectMoney;
import com.shrct.businessprocess.project.impl.RCCustomerContractImpl;
import com.shrct.businessprocess.purchase.IHasAcceptedProducts;
import com.shrct.businessprocess.purchase.RCAnonymousContractProductItem;
import com.shrct.businessprocess.purchase.RCBudgetContract;
import com.shrct.businessprocess.purchase.RCBudgetContractItem;
import com.shrct.businessprocess.purchase.RCBudgetContractNormalProductItem;
import com.shrct.businessprocess.purchase.RCBudgetContractProductItem;
import com.shrct.businessprocess.purchase.RCProductDeliver;
import com.shrct.businessprocess.purchase.events.RCBudgetContractEventsManager;
import com.shrct.businessprocess.purchase.impl.RCAnonymousContractProductItemImpl;
import com.shrct.businessprocess.purchase.impl.RCBudgetContractItemImpl;
import com.shrct.businessprocess.purchase.impl.RCBudgetContractNormalProductItemImpl;
import com.shrct.businessprocess.purchase.impl.RCBudgetContractProductItemImpl;
import com.shrct.businessprocess.purchase.impl.RCProductDeliverImpl;
import com.shrct.businessprocess.purchase.proxy.RCBudgetContractProxy;
import edu.fudan.mylang.pf.BaseModelObject;
import edu.fudan.mylang.pf.IGenericQuery;
import edu.fudan.mylang.pf.IObjectFactory;
import java.util.ArrayList;
import java.util.Collection;
import javax.persistence.AssociationOverride;
import javax.persistence.AssociationOverrides;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.eclipse.xtext.xbase.lib.CollectionLiterals;
import org.eclipse.xtext.xbase.lib.Functions.Function1;
import org.eclipse.xtext.xbase.lib.Functions.Function2;
import org.eclipse.xtext.xbase.lib.IterableExtensions;
import org.eclipse.xtext.xbase.lib.ObjectExtensions;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
import org.hibernate.annotations.DiscriminatorOptions;
import org.springframework.beans.factory.BeanFactory;

@Entity
@DiscriminatorValue("RCBUDGETCONTRACT_TYPE")
@DiscriminatorOptions(force = true)
@DiscriminatorColumn(length = 64)
@Table(name = "rcbudgetcontract")
public class RCBudgetContractImpl extends BaseModelObject implements RCBudgetContract {
  public RCBudgetContractImpl() {
    super();
  }
  
  public RCBudgetContractImpl(final RCBudget budget) {
    super();
    this.budget = budget;
  }
  
  @JoinColumn(name = "budget_id")
  @ManyToOne(targetEntity = RCBudgetImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
  private RCBudget budget;
  
  public RCBudget getBudget() {
    return this.budget;
  }
  
  public RCBudgetContract setBudget(final RCBudget budget) {
    this.budget = budget;
    return this;			
    
  }
  
  @JoinColumn(name = "customerContract_id")
  @ManyToOne(targetEntity = RCCustomerContractImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
  private RCCustomerContract customerContract;
  
  public RCCustomerContract getCustomerContract() {
    return this.customerContract;
  }
  
  public RCBudgetContract setCustomerContract(final RCCustomerContract customerContract) {
    this.customerContract = customerContract;
    return this;			
    
  }
  
  @Embedded
  @AttributeOverrides(value = { @AttributeOverride(name = "amount", column = @Column(name = "amount_amount") ), @AttributeOverride(name = "workaround", column = @Column(name = "amount_workaround") ) } )
  @AssociationOverrides(value = @AssociationOverride(name = "exchange", joinColumns = @JoinColumn(name = "amount_exchange") ) )
  private RCProjectMoney amount = com.shrct.businessprocess.project.RCProjectMoney.create();
  
  public RCProjectMoney getAmount() {
    return this.amount;
  }
  
  public RCBudgetContract setAmount(final RCProjectMoney amount) {
    this.amount = amount;
    return this;			
    
  }
  
  public String getContractId() {
    String _contractId = this.customerContract.getContractId();
    return _contractId;
  }
  
  public RCEnterprise getCustomer() {
    RCEnterprise _customer = this.customerContract.getCustomer();
    return _customer;
  }
  
  @OneToMany(targetEntity = RCBudgetContractItemImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE }, mappedBy = "contract")
  private Collection<RCBudgetContractItem> contratItems = new java.util.ArrayList<com.shrct.businessprocess.purchase.RCBudgetContractItem>();;
  
  public Collection<RCBudgetContractItem> getContratItems() {
    return this.contratItems;
  }
  
  public RCBudgetContract removeAllContratItems() {
    for(RCBudgetContractItem obj : this.contratItems){
    	getObjectFactory().delete(obj);
    }
    this.contratItems.clear();
    return this;	
    
  }
  
  public RCBudgetContract removeFromContratItems(final RCBudgetContractItem rCBudgetContractItem) {
    this.contratItems.remove(rCBudgetContractItem);
    getObjectFactory().delete(rCBudgetContractItem);
    return this;
    
  }
  
  @OneToMany(targetEntity = RCProductDeliverImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE }, mappedBy = "contract")
  private Collection<RCProductDeliver> delivers = new java.util.ArrayList<com.shrct.businessprocess.purchase.RCProductDeliver>();;
  
  public Collection<RCProductDeliver> getDelivers() {
    return this.delivers;
  }
  
  public RCProductDeliver createAndAddtoDelivers() {
    getDelivers().size();
    com.shrct.businessprocess.purchase.RCProductDeliver rCProductDeliver = new com.shrct.businessprocess.purchase.impl.RCProductDeliverImpl(this);
    getObjectFactory().create(rCProductDeliver);
    getDelivers().add(rCProductDeliver);
    return rCProductDeliver;
    
  }
  
  public RCProductDeliver createAndAddtoDelivers(final Procedure1<RCProductDeliver> updater) {
    getDelivers().size();
    com.shrct.businessprocess.purchase.RCProductDeliver rCProductDeliver = new com.shrct.businessprocess.purchase.impl.RCProductDeliverImpl(this);
    getObjectFactory().create(rCProductDeliver);
    getDelivers().add(rCProductDeliver);
    return rCProductDeliver;
    
  }
  
  public RCBudgetContract removeAllDelivers() {
    for(RCProductDeliver obj : this.delivers){
    	getObjectFactory().delete(obj);
    }
    this.delivers.clear();
    return this;	
    
  }
  
  public RCBudgetContract removeFromDelivers(final RCProductDeliver rCProductDeliver) {
    this.delivers.remove(rCProductDeliver);
    getObjectFactory().delete(rCProductDeliver);
    return this;
    
  }
  
  public RCProjectMoney getTotalAmount() {
    return this.amount;
  }
  
  public RCProjectMoney getTotalListAmount() {
    RCProjectMoney _xblockexpression = null;
    {
      final Function1<RCBudgetContractItem,RCProjectMoney> _function = new Function1<RCBudgetContractItem,RCProjectMoney>() {
          public RCProjectMoney apply(final RCBudgetContractItem it) {
            RCProjectMoney _price = it.getPrice();
            return _price;
          }
        };
      Iterable<RCProjectMoney> _map = IterableExtensions.<RCBudgetContractItem, RCProjectMoney>map(this.contratItems, _function);
      final Function2<RCProjectMoney,RCProjectMoney,RCProjectMoney> _function_1 = new Function2<RCProjectMoney,RCProjectMoney,RCProjectMoney>() {
          public RCProjectMoney apply(final RCProjectMoney m1, final RCProjectMoney m2) {
            RCProjectMoney _plus = m1.plus(m2);
            return _plus;
          }
        };
      RCProjectMoney result = IterableExtensions.<RCProjectMoney>reduce(_map, _function_1);
      RCProjectMoney _xifexpression = null;
      boolean _equals = Objects.equal(result, null);
      if (_equals) {
        RCProjectMoney _rCProjectMoney = new RCProjectMoney();
        final Procedure1<RCProjectMoney> _function_2 = new Procedure1<RCProjectMoney>() {
            public void apply(final RCProjectMoney it) {
              it.setAmount(Double.valueOf(0d));
              RCExchangeRate _defaultContractExchangeRate = RCBudgetContractImpl.this.budget.getDefaultContractExchangeRate();
              it.setExchange(_defaultContractExchangeRate);
            }
          };
        RCProjectMoney _doubleArrow = ObjectExtensions.<RCProjectMoney>operator_doubleArrow(_rCProjectMoney, _function_2);
        _xifexpression = _doubleArrow;
      } else {
        RCExchangeRate _defaultContractExchangeRate = this.budget.getDefaultContractExchangeRate();
        RCProjectMoney _money = result.toMoney(_defaultContractExchangeRate);
        _xifexpression = _money;
      }
      _xblockexpression = (_xifexpression);
    }
    return _xblockexpression;
  }
  
  public RCProjectMoney getTotalListAmount(final RCProductSpecification productSpec) {
    RCProjectMoney _xblockexpression = null;
    {
      final Function1<RCBudgetContractItem,Boolean> _function = new Function1<RCBudgetContractItem,Boolean>() {
          public Boolean apply(final RCBudgetContractItem it) {
            RCProductSpecification _productSpec = it.getProductSpec();
            boolean _equals = Objects.equal(_productSpec, productSpec);
            return Boolean.valueOf(_equals);
          }
        };
      Iterable<RCBudgetContractItem> _filter = IterableExtensions.<RCBudgetContractItem>filter(this.contratItems, _function);
      final Function1<RCBudgetContractItem,RCProjectMoney> _function_1 = new Function1<RCBudgetContractItem,RCProjectMoney>() {
          public RCProjectMoney apply(final RCBudgetContractItem it) {
            RCProjectMoney _price = it.getPrice();
            return _price;
          }
        };
      Iterable<RCProjectMoney> _map = IterableExtensions.<RCBudgetContractItem, RCProjectMoney>map(_filter, _function_1);
      final Function2<RCProjectMoney,RCProjectMoney,RCProjectMoney> _function_2 = new Function2<RCProjectMoney,RCProjectMoney,RCProjectMoney>() {
          public RCProjectMoney apply(final RCProjectMoney m1, final RCProjectMoney m2) {
            RCProjectMoney _plus = m1.plus(m2);
            return _plus;
          }
        };
      RCProjectMoney result = IterableExtensions.<RCProjectMoney>reduce(_map, _function_2);
      RCProjectMoney _xifexpression = null;
      boolean _equals = Objects.equal(result, null);
      if (_equals) {
        RCProjectMoney _rCProjectMoney = new RCProjectMoney();
        final Procedure1<RCProjectMoney> _function_3 = new Procedure1<RCProjectMoney>() {
            public void apply(final RCProjectMoney it) {
              it.setAmount(Double.valueOf(0d));
              RCExchangeRate _defaultContractExchangeRate = RCBudgetContractImpl.this.budget.getDefaultContractExchangeRate();
              it.setExchange(_defaultContractExchangeRate);
            }
          };
        RCProjectMoney _doubleArrow = ObjectExtensions.<RCProjectMoney>operator_doubleArrow(_rCProjectMoney, _function_3);
        _xifexpression = _doubleArrow;
      } else {
        RCExchangeRate _defaultContractExchangeRate = this.budget.getDefaultContractExchangeRate();
        RCProjectMoney _money = result.toMoney(_defaultContractExchangeRate);
        _xifexpression = _money;
      }
      _xblockexpression = (_xifexpression);
    }
    return _xblockexpression;
  }
  
  public Iterable<RCProductEntry> getAllAcceptedProducts() {
    Iterable<RCProductEntry> _xifexpression = null;
    if ((this.budget instanceof IHasAcceptedProducts)) {
      Iterable<RCProductEntry> _allAcceptedProducts = ((IHasAcceptedProducts) this.budget).getAllAcceptedProducts();
      _xifexpression = _allAcceptedProducts;
    } else {
      ArrayList<RCProductEntry> _newArrayList = CollectionLiterals.<RCProductEntry>newArrayList();
      _xifexpression = _newArrayList;
    }
    return _xifexpression;
  }
  
  public RCBudgetContractProductItem createProductItem() {RCBudgetContractProductItem rCBudgetContractProductItem=RCBudgetContractProductItemImpl.create(this,getObjectFactory());
    final Procedure1<RCBudgetContractProductItem> _function = new Procedure1<RCBudgetContractProductItem>() {
        public void apply(final RCBudgetContractProductItem it) {
          RCBudgetContractImpl.this.contratItems.add(it);
        }
      };
    RCBudgetContractProductItem _doubleArrow = ObjectExtensions.<RCBudgetContractProductItem>operator_doubleArrow(rCBudgetContractProductItem, _function);
    return _doubleArrow;
  }
  
  public RCBudgetContractNormalProductItem createNormalProductItem() {RCBudgetContractNormalProductItem rCBudgetContractNormalProductItem=RCBudgetContractNormalProductItemImpl.create(this,getObjectFactory());
    final Procedure1<RCBudgetContractNormalProductItem> _function = new Procedure1<RCBudgetContractNormalProductItem>() {
        public void apply(final RCBudgetContractNormalProductItem it) {
          RCBudgetContractImpl.this.contratItems.add(it);
        }
      };
    RCBudgetContractNormalProductItem _doubleArrow = ObjectExtensions.<RCBudgetContractNormalProductItem>operator_doubleArrow(rCBudgetContractNormalProductItem, _function);
    return _doubleArrow;
  }
  
  public RCAnonymousContractProductItem createAnonymouseProductItem() {RCAnonymousContractProductItem rCAnonymousContractProductItem=RCAnonymousContractProductItemImpl.create(this,getObjectFactory());
    final Procedure1<RCAnonymousContractProductItem> _function = new Procedure1<RCAnonymousContractProductItem>() {
        public void apply(final RCAnonymousContractProductItem it) {
          RCBudgetContractImpl.this.contratItems.add(it);
        }
      };
    RCAnonymousContractProductItem _doubleArrow = ObjectExtensions.<RCAnonymousContractProductItem>operator_doubleArrow(rCAnonymousContractProductItem, _function);
    return _doubleArrow;
  }
  
  public Iterable<RCProductServiceTracer> getRCProductServiceTracer() {
    IGenericQuery<RCProductServiceTracer> query=getObjectFactory().createGenericQuery(RCProductServiceTracer.class,"select e from com.shrct.businessprocess.product.impl.RCProductServiceTracerImpl as e   where ((e.budgetContract) = (:this)) and  e.active = 1      ").setParameter("this",this);
    Collection<RCProductServiceTracer> _list = query.list();
    return _list;
  }
  
  public void updateAmount(final RCProjectMoney amount) {
    this.amount = amount;
    BeanFactory _beanFactory = this.getBeanFactory();
    RCBudgetContractEventsManager _bean = _beanFactory.<RCBudgetContractEventsManager>getBean(RCBudgetContractEventsManager.class);
    _bean.fireAmountChanged(this);
  }
  
  public static RCBudgetContract create(final RCBudget budget, final IObjectFactory objectFactory) {
    com.shrct.businessprocess.purchase.RCBudgetContract rCBudgetContract = new com.shrct.businessprocess.purchase.impl.RCBudgetContractImpl(
    	budget
    );
    objectFactory.create(rCBudgetContract);
    return rCBudgetContract;			
    
  }
  
  public static RCBudgetContract createRCBudgetContractImpl(final RCBudget budget, final IObjectFactory objectFactory, final Procedure1<RCBudgetContract> init) {
    com.shrct.businessprocess.purchase.RCBudgetContract rCBudgetContract = new com.shrct.businessprocess.purchase.impl.RCBudgetContractImpl(
    	budget
    );
    objectFactory.create(rCBudgetContract);
    init.apply(rCBudgetContract);
    
    return rCBudgetContract;			
    
  }
  
  public RCBudgetContractProxy toProxy() {
    com.shrct.businessprocess.purchase.proxy.RCBudgetContractProxy proxy = new com.shrct.businessprocess.purchase.proxy.RCBudgetContractProxy();
    proxy.setId(this.getId());
    if(this instanceof edu.fudan.mylang.pf.INamedModelObject){
    	proxy.setName(((edu.fudan.mylang.pf.INamedModelObject)this).getEntityName());
    }
    return proxy;
    
  }
}
